package cn.ant.config;

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;

import java.util.HashMap;
import java.util.Map;


/**
 * 关于延迟队列模块的RabbitMQ配置信息
 * 一定需要加@SpringBootConfiguration注解，标注当前为配置类，交由Spring管理。
 *
 * @author Anhui AntLaddie <a href="https://juejin.cn/user/4092805620185316">(掘金蚂蚁小哥)</a>
 * @version 1.0
 **/
@SpringBootConfiguration
public class RabbitMQConfig {

    // 定义1：简单的直接交换机名称；定义2：简单队列名称；定义3：路由key
    public static final String PRIORITY_DIRECT_EXCHANGE = "priorityDirectExchange";
    public static final String PRIORITY_QUEUE_NAME = "priorityQueueName";
    public static final String PRIORITY_KEY = "priorityKey";

    /***
     * 创建交换机信息；
     * @return Exchange
     */
    @Bean(value = "priorityDirectExchange")
    public Exchange createPriorityDirectExchange() {
        return ExchangeBuilder
                .directExchange(PRIORITY_DIRECT_EXCHANGE)
                .durable(true)
                .build();
    }

    /**
     * 创建一个具备优先级支持的持久化队列。
     * 此队列允许消费者根据消息设置的优先级（priority）顺序进行消费。
     * <p>
     * RabbitMQ 官方支持的优先级范围是 0~255。
     * 实际项目中建议使用 0~10 范围，优先级越高，越早被消费。
     * <p>
     * ⚠️ 注意：
     * - 如果消息没有设置优先级，默认优先级为 0。
     * - 优先级设置过大，会造成调度开销增加，建议控制在合理范围内。
     * - 不是所有消息都应设置为高优先级，避免“优先级失效”。
     *
     * @return 创建后的优先级队列对象 Queue
     */
    @Bean(value = "priorityQueueName")
    public Queue createPriorityQueueName() {
        // 定义优先级队列的参数
        Map<String, Object> args = new HashMap<>();

        // 设置队列支持的最大优先级（官方支持 0~255，这里设置为 10）
        // 设置过大可能导致 RabbitMQ 内部排序耗费较多资源（性能问题）
        args.put("x-max-priority", 10);

        // 构建一个持久化（durable=true）、非独占（exclusive=false）、不自动删除的队列
        // 设置了 x-max-priority 参数以支持消息优先级
        return QueueBuilder
                .durable(PRIORITY_QUEUE_NAME)  // 队列名为 PRIORITY_QUEUE_NAME（应为常量）
                .withArguments(args)           // 设置参数
                .build();                      // 构建队列
    }

    /***
     * 将队列信息绑定到交换机上
     * @param priorityDirectExchange 简单的直接交换机
     * @param priorityQueueName 简单的队列
     * @return Binding
     */
    @Bean(value = "priorityQueueBindPriorityExchange")
    public Binding createPriorityQueueBindPriorityExchange(
            @Qualifier(value = "priorityDirectExchange") Exchange priorityDirectExchange,
            @Qualifier(value = "priorityQueueName") Queue priorityQueueName) {
        return BindingBuilder
                .bind(priorityQueueName).to(priorityDirectExchange).with(PRIORITY_KEY).noargs();
    }
}
